#ifndef _FNT_TRACER_H_
#define _FNT_TRACER_H_

#include <QApplication>
#include <sstream>
#include "utils.h"

class QAction;
class QMenu;

class Session;
class Options;

class LoadThreadShared;
class ViewerShared;

enum class SessionState;

enum TracerAction {
	SESSION_NEW=0,
	SESSION_OPEN,
	/* rescent & recover submenus*/

	TRACER_SETTINGS,

	TRACER_QUIT,

	TRACER_MANUAL,
	TRACER_ABOUT,

	TRACER_ACTION_NUM
};

enum class TracerState {
	Invalid,
	Restricted,
	Ready
};

struct TracerPriv;
class Tracer: public QApplication {
	Q_OBJECT;
	friend struct TracerPriv;
	TracerPriv*const priv;

	static Tracer* _instance;

	bool notify(QObject* receiver, QEvent* event) override;

	Tracer(int& argc, char** argv);

	void logMessageHelper(const std::string& s) const;

	private Q_SLOTS:
		void createSession();
	void openSession();
	void openSessionRecent();
	void clearRecentList();
	void openSessionRecover();
	void clearRecoverList();
	void showSettings();
	void showManual();
	void showAbout();
	void quitTracer();

	void cacheWarning(const QString& msg);
	void cacheError(const QString& msg);
	void requestLogin(const QString& url, const QString& oldusr, const QString& oldpwd);

	void sessionRequestClose(Session* s);
	void sessionReady(Session* s, bool err);
	void sessionFocusChanged(QWidget* w0, QWidget* w1);
	void sessionStateChanged(Session* s, SessionState ss);

	public Q_SLOTS:

	public:
		static Tracer* create(int& argc, char** argv);
		static Tracer* instance() {
			if(!_instance) {
				int argc=0;
				char** argv{nullptr};
				_instance=new Tracer{argc, argv};
			}
			return _instance;
		}
		~Tracer();

		void start();

		const std::array<QAction*, TRACER_ACTION_NUM>& tracerActions() const;
		QMenu* recentMenu() const;
		QMenu* recoverMenu() const;
		Options* options() const;

		LoadThreadShared* loaderShared() const;
		ViewerShared* viewerShared() const;

		template<typename... Args> inline void logMessage(Args&&... args) const {
			std::ostringstream oss;
			printToStream(oss, std::forward<Args>(args)...);
			logMessageHelper(oss.str());
		}
};

#endif
